package cnsatmsmart.automation.mmi.controller.client;

import cnsatmsmart.CNSATMSMARTApp;
import cnsatmsmart.CNSATMSMARTView;
import cnsatmsmart.automation.mmi.controller.Buffer.Asterix21Data;
import cnsatmsmart.automation.mmi.controller.Buffer.Asterix21DataList;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

/**
 * Merupakan kelas client yang menerima data dari server secara unicast
 * @author SIK -PTIK, BPPT
 */
public class ClientThread implements Runnable{
	
    /* Atribut-atribut yang dimiliki oleh kelas ClientThread */
        private Asterix21DataList Ax21DataList;
        private boolean KeepConnect;
	private DataInputStream InputStream;
	private int Port;
	private Socket ClientSocket;
	private String Host;
        
    /* Constructor - user defined constructor, no default constructor */
        /**
         * Konstruktor
         * @param port Port
         * @param host Host
         * @param ax21DataList List dari data asterix yang digunakan untuk menampung data dari server
         */
        public ClientThread(int port, String host, Asterix21DataList ax21DataList)
	{
            this.Port = port;
            this.Host = host;
            this.Ax21DataList = ax21DataList;
	}
   
    /* Method-method untuk thread */
        /**
         * Fungsi untuk membangun koneksi dengan server
         * @return Mengembalikan true jika koneksi telah terbentuk, false jika gagal
         */
        public boolean Connect()
	{
            boolean ret = false;
            try
            {
                ClientSocket = new Socket (Host, Port);
                InputStream = new DataInputStream (ClientSocket.getInputStream());
                KeepConnect = true;
                ret = true;
            }
            catch (SocketException e)
            {
                ret = false;
            }
            catch (UnknownHostException e)
            {
                ret = false;
            }
            catch (IOException e)
            {
                ret = false;
            }
            return ret;
	}
	
	//Close Connection
        /**
         * Keluar dari thread
         * @throws IOException
         */
        public void Close() throws IOException
	{
            if (KeepConnect)
            {
                KeepConnect = false;
            }
            else
            {
                System.out.println("No Connection.");
            }
	}
	
	/**
         * Fungsi untuk mendapatkan data dari server
         * @return Mengembalikan true jika ada data yang didapat, false jika tidak ada data yang didapat
         */
        private boolean getData()
	{
            boolean Success = false;
            int i = 0;
            int bufferLen;
            short input, octetHigh, octetLow;
            short cat, length1, length2;
            short[] arrdata = new short[2048];

            if (KeepConnect)
            {
                try
                {
                    //Input dibaca dari data 0x0015, oleh karena itu iterasi dilakukan sampai mendapatkan data 0x015
                    do
                    {
                        //Membaca data dari server dengan DataInputStream
                        input = InputStream.readByte();
                        input = (short) (input & 0x00FF);
                    }
                    while (input != (short) 0x0015);

                    //Data yang masuk dimasukan ke dalam variabel cat, octetHigh, octetLow, dan arrdata
                    cat = input;
                    octetHigh = InputStream.readByte();
                    length1 = (short) (octetHigh & 0x00FF);
                    octetLow = InputStream.readByte();
                    length2 = (short) (octetLow & 0x00FF);
                    bufferLen = 256 * octetHigh + octetLow;

                    while (i < bufferLen - 3)
                    {
                        arrdata[i++] = (short) ((InputStream.readByte()) & 0x00FF);
                    }

                    //Data kemudian dimasukan sebagai Asterix21Data ke Asterix21DataList
                    Asterix21Data ax21 = new Asterix21Data(cat, length1, length2, arrdata, bufferLen);
                    this.Ax21DataList.AddAx21Data(ax21);
                    
                    Success = true;
                }
                catch (IOException e)
                {
                    Success = false;
                }
            }
            else
            {
                System.out.println("No connection to get data.");
            }

            return (Success);
	}
	
	public void run()
	{
            CNSATMSMARTView view = (CNSATMSMARTView)CNSATMSMARTApp.getApplication().getMainView();
            while (KeepConnect)
            {
                //Jika tidak mendapatkan data dari server, maka koneksi diputuskan
                if (!getData())
                {
                    try {
                        Close();
                    } catch (IOException ex) {
                        Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
                    }

                    // show a joptionpane dialog using showMessageDialog
                    JOptionPane.showMessageDialog(new JFrame(), "Disconnect.");                

                    try {
                        view.Disconnect(false);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (IOException ex) {
                        Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }

            try {
                InputStream.close();
                ClientSocket.close();   
            } catch (IOException ex) {
                Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
            }

            //Thread sleep sementara untuk menunggu koneksi telah benar2 terputus
            try {
                Thread.sleep(600);
            } catch (InterruptedException ex) {
                Logger.getLogger(ClientThread.class.getName()).log(Level.SEVERE, null, ex);
            }
	}
}
